﻿using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace ZyGame.Execute
{
    public class ParallelRunnable : Runnable<object>
    {
        private Exception _ex;
        private List<Running> untils = new List<Running>();
        private Queue<Running> finishs = new Queue<Running>();

        public override void Dispose()
        {
            untils.Clear();
            untils = null;
            finishs.Clear();
            finishs = null;
            GC.SuppressFinalize(this);
        }

        protected override IEnumerator DoRunning()
        {
            for (int i = 0; i < untils.Count; i++)
            {
                Client.Tools.StartCoroutine(OnStartRunnig(untils[i]));
            }
            yield return new WaitUntil(CheckCompleted);
            while (finishs.TryDequeue(out Running running))
            {
                yield return OnStartRunnig(running);
            }
            state = RunState.Completed;
            RunnableManager.instance.Remove(name);
        }

        private IEnumerator OnStartRunnig(Running running)
        {
            if (running is null)
            {
                yield break;
            }
            yield return running.Runnable();
            running.Dispose();
        }

        protected override bool CheckCompleted()
        {
            if (state == RunState.Completed || state == RunState.Canceled)
            {
                return true;
            }
            return untils.Find(x => x.state != RunState.Completed && x.state != RunState.Canceled) == null;
        }

        public override Runnable<object> Execute(Func<IEnumerator> func)
        {
            untils.Add(new Running(func));
            return this;
        }

        public ParallelRunnable DoFinish(Func<IEnumerator> action)
        {
            finishs.Enqueue(new Running(action));
            return this;
        }
    }
}